package com.caffeinatedbliss.nanowrimo;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.text.MessageFormat;

public class WordWarGraph implements DynamicImageGenerator {
  private static final int CURVE_RADIUS = 8;

  public static final Color LIGHTEST_GREY = new Color(0xf0, 0xf0, 0xf0);
  public static final Color NOT_SO_LIGHTEST_GREY = new Color(0xbb, 0xbb, 0xdd);
  private static final GradientPaint GRADIENT = new GradientPaint(WordWarGraph.CURVE_RADIUS, WordWarGraph.CURVE_RADIUS,
    WordWarGraph.LIGHTEST_GREY, 6 * WordWarGraph.CURVE_RADIUS, WordWarGraph.CURVE_RADIUS * 6, WordWarGraph.NOT_SO_LIGHTEST_GREY, false);

  public static final Color GREY_BORDER = new Color(0xbb, 0xbb, 0xbb);
  public static final Color DK_GREY_BORDER = new Color(0x99, 0x99, 0x99);
  private static final GradientPaint OUTSIDE_GRADIENT = new GradientPaint(WordWarGraph.CURVE_RADIUS, WordWarGraph.CURVE_RADIUS,
    WordWarGraph.GREY_BORDER, 6 * WordWarGraph.CURVE_RADIUS, WordWarGraph.CURVE_RADIUS * 6, WordWarGraph.DK_GREY_BORDER, false);

  public static final Color GRAPH_BACKGROUND = new Color(0xee, 0xee, 0xee);
  public static final Color GREEN_INK = new Color(0x00, 0xcc, 0x00);

  private BufferedImage graphImage;
  private static final Font NON_BOLD_TEXT_FONT = new Font("dialog", Font.PLAIN, 11);
  private static final Font TEXT_FONT = new Font("dialog", Font.BOLD, 11);

  public WordWarGraph(int goal, int width, String[] names, int[] amounts, int[] people, String wordcountFormat) {
    graphImage = new BufferedImage(width, names.length * 40 + 1, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = (Graphics2D) graphImage.getGraphics();

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    drawFilledRectangleWithCurvedCorners(g, width, names.length * 40 + 1);

    NanowrimoComputer computer = new NanowrimoComputer(amounts, goal);
    for (int i = 0; i < names.length; i++) {
      drawName(g, names[i], i * 40 - 3, width);
      drawAmount(g, amounts[i], people[i], i * 40 + 22, width, computer.getPercentComplete(), computer.getDaysLeftNaNoWriMo(), wordcountFormat);
    }

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
    for (int i = 0; i < names.length; i++) {
      drawPercentCompleteBar(g, amounts[i], goal, i * 40 + 15, width);
    }

    g.dispose();
  }

  private void drawAmount(Graphics2D g, int amount, int people, int yPos, int width, double percentComplete, int daysLeftNaNoWriMo, String wordcountFormat) {
    g.setColor(Color.black);
    double averageUserInRegion = (people > 0) ? (amount/people) : 0;
    String text = MessageFormat.format(wordcountFormat, amount, daysLeftNaNoWriMo, percentComplete, averageUserInRegion, people);
    drawCenteredText(g, WordWarGraph.NON_BOLD_TEXT_FONT, text, yPos, width);
  }

  private void drawPercentCompleteBar(Graphics2D g, int amount, int goal, int yPos, int width) {
    double percentComplete = (double) amount / (double) goal * 100.0;
    if (percentComplete < 0) {
      percentComplete = 0;
    } else if (percentComplete > 100) {
      percentComplete = 100;
    }
    int green = (int) (1 + (width - 15) * percentComplete / 100.0);
    g.setColor(WordWarGraph.GREY_BORDER);
    g.drawRect(5, yPos, width - 11, 10);
    g.setColor(WordWarGraph.GRAPH_BACKGROUND);
    g.fillRect(6, yPos + 1, width - 13, 9);
    g.setColor(WordWarGraph.GREEN_INK);
    g.fillRect(7, yPos + 2, green, 7);
  }

  private void drawName(Graphics2D g, String name, int yPos, int width) {
    g.setColor(Color.black);
    drawCenteredText(g, WordWarGraph.TEXT_FONT, name, yPos, width);
  }

  private void drawCenteredText(Graphics g, Font textFont, String aTextString, int yPos, int width) {
    if (aTextString == null) {
      return;
    }
    g.setFont(textFont);
    FontMetrics fm = g.getFontMetrics(textFont);
    int ascent = fm.getAscent();
    int descent = fm.getDescent();
    int totalLineHeght = ascent + descent;
    int wordWidth = fm.stringWidth(aTextString);
    int leftEdge = (width - wordWidth) / 2;
    g.drawString(aTextString, leftEdge, yPos + totalLineHeght);
  }

  private void drawFilledRectangleWithCurvedCorners(Graphics2D g, int width, int height) {
    g.setPaint(WordWarGraph.GRADIENT);
    g.fillRoundRect(0, 0, width - 1, height - 1, 2 * WordWarGraph.CURVE_RADIUS, 2 * WordWarGraph.CURVE_RADIUS);

    g.setPaint(WordWarGraph.OUTSIDE_GRADIENT);
    g.drawRoundRect(0, 0, width - 1, height - 1, 2 * WordWarGraph.CURVE_RADIUS, 2 * WordWarGraph.CURVE_RADIUS);

  }

  public BufferedImage getGraphImage() {
    return graphImage;
  }
}
